/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.knolle.vistas;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.LinkedList;
import java.util.List;
import javax.swing.JOptionPane;
import javax.swing.SwingWorker;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.table.AbstractTableModel;
import org.marcelo.agro.entidades.Productos;
import org.marcelo.agro.core.api.InterfaceProductos;
import org.openide.DialogDescriptor;
import org.openide.awt.StatusDisplayer;
import org.openide.util.Lookup;

/**
 *
 * @author marcelo
 */
public class PanelSeleccionarProducto extends javax.swing.JPanel implements ActionListener{

    /**
     * Creates new form PanelSeleccionarProducto
     */
    
    private Productos producto;
    private ProductosTableModel tablaModel;
//    private modelo.LotesPorCampana lpc;
//    Worker
    private PeticionTablaWorker ptw = null;
//    Textos para mostrar mensajes de error u otros eventos
    private static final String MENSAJE_RESULTADO = "Total Encontrados: ";
    private static final String MENSAJE_SELECCIONADO = "Seleccionado: ";
    
    public PanelSeleccionarProducto() {
        initComponents();
        AddListeners();
        tareasAsync();
    }
//    Para colocar los listener en la tabla y "Escuchar" los eventos del mouse y selecccion del con el teclado
    private void AddListeners(){
        TablaProductos.addMouseListener(new java.awt.event.MouseAdapter() {
            @Override
           public void mouseClicked(java.awt.event.MouseEvent evt){
                TablaProductosMouseClicked();
           }
       
       });
       TablaProductos.getSelectionModel().addListSelectionListener(new javax.swing.event.ListSelectionListener() {

            @Override
            public void valueChanged(ListSelectionEvent e) {
                if (TablaProductos.getRowSelectionAllowed() && e.getSource().equals(TablaProductos.getSelectionModel())){
                    TablaProductosMouseClicked();
                }
            }
        });
    
    }
    
    /**
     * Este metodo agrega un listener al campo CampoNombreProducto, para realizar consultas en la base de datos de forma
     * asincrona, 
     */
    private void tareasAsync(){
    
       this.CampoNombreProducto.getDocument().addDocumentListener(new DocumentListener() {
           
            private void ejecutarAync(DocumentEvent e){
                   ptw = new PeticionTablaWorker();
                   
                    ptw.addPropertyChangeListener(new PropertyChangeListener() {
                        @Override
                        public void propertyChange(PropertyChangeEvent evt) {
                            if (evt.getNewValue() == SwingWorker.StateValue.STARTED) {
                               jButton1.setEnabled(false);
                            }
                            else if (evt.getNewValue() == SwingWorker.StateValue.DONE){
                                jButton1.setEnabled(true);
                            }
                        }
                    }
                    );
                    ptw.execute();
           
            }
           
            @Override
            public void insertUpdate(DocumentEvent e) {
               if (null != ptw)
                    ptw.cancel(true);
               ejecutarAync(e);
            }

            @Override
            public void removeUpdate(DocumentEvent e) {
                if (null != ptw)
                    ptw.cancel(true);
                ejecutarAync(e);
            }

            @Override
            public void changedUpdate(DocumentEvent e) {
                if (null != ptw)
                    ptw.cancel(true);
                ejecutarAync(e);
          }
        });
    }
    
//    public PanelSeleccionarProducto(modelo.LotesPorCampana lpc){
//       initComponents();
//       this.lpc = lpc;       
//       tareasAsync();
//       AddListeners();
//    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jScrollPane1 = new javax.swing.JScrollPane();
        TablaProductos = new javax.swing.JTable();
        CampoNombreProducto = new javax.swing.JTextField();
        jButton1 = new javax.swing.JButton();
        CampoResultados = new javax.swing.JLabel();
        lblSeleccionado = new javax.swing.JLabel();

        jScrollPane1.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                jScrollPane1MouseClicked(evt);
            }
        });

        //Modelo Para la tabla
        tablaModel= new ProductosTableModel();
        //Seteando el Modelo
        TablaProductos.setModel(tablaModel);
        jScrollPane1.setViewportView(TablaProductos);

        CampoNombreProducto.setText(org.openide.util.NbBundle.getMessage(PanelSeleccionarProducto.class, "PanelSeleccionarProducto.CampoNombreProducto.text")); // NOI18N

        jButton1.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/marcelo/agro/campanias/recursos/Magnifier_24x24.png"))); // NOI18N
        jButton1.setText(org.openide.util.NbBundle.getMessage(PanelSeleccionarProducto.class, "PanelSeleccionarProducto.jButton1.text")); // NOI18N
        jButton1.addActionListener(this);

        CampoResultados.setText(org.openide.util.NbBundle.getMessage(PanelSeleccionarProducto.class, "PanelSeleccionarProducto.CampoResultados.text")); // NOI18N
        CampoResultados.setVisible(false);

        lblSeleccionado.setText(org.openide.util.NbBundle.getMessage(PanelSeleccionarProducto.class, "PanelSeleccionarProducto.lblSeleccionado.text")); // NOI18N
        lblSeleccionado.setVisible(false);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(CampoNombreProducto)
                        .addGap(18, 18, 18)
                        .addComponent(jButton1))
                    .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 418, Short.MAX_VALUE)
                    .addComponent(lblSeleccionado, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(CampoResultados, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(CampoNombreProducto, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jButton1))
                .addGap(18, 18, 18)
                .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 191, Short.MAX_VALUE)
                .addGap(18, 18, 18)
                .addComponent(lblSeleccionado)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(CampoResultados)
                .addContainerGap())
        );
    }// </editor-fold>//GEN-END:initComponents

    private void jScrollPane1MouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jScrollPane1MouseClicked
        // TODO add your handling code here:
    }//GEN-LAST:event_jScrollPane1MouseClicked
    
    private void TablaProductosMouseClicked(){
        int i = TablaProductos.getSelectedRow();
        if ( i >= 0){
            this.producto =  (Productos)((ProductosTableModel) TablaProductos.getModel()).getList().get(i);
            this.lblSeleccionado.setText(MENSAJE_SELECCIONADO + this.producto.getNombre());
            lblSeleccionado.setVisible(true);
        }
        else {
          this.producto=null;
          lblSeleccionado.setVisible(false);
        }
    }
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JTextField CampoNombreProducto;
    private javax.swing.JLabel CampoResultados;
    private javax.swing.JTable TablaProductos;
    private javax.swing.JButton jButton1;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JLabel lblSeleccionado;
    // End of variables declaration//GEN-END:variables

    @Override
    public void actionPerformed(ActionEvent e) {
        if (e.getSource().equals(jButton1)) {
           if (null != ptw)
                ptw.cancel(true);
            ptw = new PeticionTablaWorker();
            ptw.execute();
        }
        
        else if (e.getSource().equals(DialogDescriptor.OK_OPTION)){
            System.out.print("Presiono OK");
            return;
        }
        else if (e.getSource().equals(DialogDescriptor.CANCEL_OPTION)){
            System.out.print("Presiono cancel");
            return;
        }
        
    }
    
    /**
     * Devolver el producto seleccionado
     * @return 
     */
    public Productos getProducto(){
       return this.producto;
    }



    
    
    private class BuscarProductoPropertyListener implements PropertyChangeListener{

        
        @Override
        public void propertyChange(PropertyChangeEvent evt) {
            Object source = evt.getSource();
            //Si la fuente es la misma que CampoBuscar entonces consultar en la base de datos
            //Para realizar la consultas pertinentes
            if (source == CampoNombreProducto) {
                //La cuestion es abrir la sesion y dejarla abierta para que no se habra y cierre con cada peticion
                //ya que esto acarreara muchos problemas, mucho codigo, mejor llamar a OpenSesion(), luego la llamada a 
                //doInBackground(), para que utilize la misma session, porner un lock, o algo asi, ya que no se si en cada
                //tecleada va a crear una instancia
                //Es el mismo se procede a buscar los datos en la base de datos, 
                //me imagino que seria bueno que sea en background, crear una instancia de PeticionTablaWorker()
                //llamar al metodo doInBackground(), cuando termina refrescar la GUI
                //cargar los datos en el Model de la tabla
                //Antes de llamar setear los campos en el objeto producto
                //Por ahora voy a forzar los ID de tipoProducto
                //tengo que tener un buffer, asi antes de pedir x veces lo mismo espero que se cargue por lo menos una par de veces
                producto.setNombre((String)evt.getNewValue());
                if (ptw == null) {
                    ptw = new PeticionTablaWorker();
                    ptw.execute();
                }
                else {
                    //Hay algo que se esta ejecutando, cancelar, esperar hasta que cancele
                    //volver a llamar con los nuevos datos
                    if (ptw.isCancelled()) {
                       //Fue cancelado
                    }
                    else if (ptw.isDone()){
                       //Termino 
                    }
                }
                //Producir el renderizado de la tabla mediante fireDataSetChange
//                TablaProductos.getModel();
            }
            JOptionPane.showMessageDialog(null,"Cambiando valores");
        }
    
    }
    
    private class ProductosTableModel extends AbstractTableModel {

        //Campos para mostrar en la tabla produtos
        private final int CAMPO_ID=100;
        private final int CAMPO_NOMBRE=0;
        private final int CAMPO_TIPO_PRODUCTO=1;
        private final int CAMPO_TIPO_PRESENTACION=2;
        private final int CAMPO_FABRICANTE=3;
        private final int CAMPO_REGISTRANTE=4;
        private final int CAMPO_TOXICIDAD=5;
        
        private String[] columnNames = {"Nombre", "Tipo Producto","Tipo Presentacion", "Fabricante", "Representante", "Toxicidad" }; 
    
        private List<Productos> productosList ;
        
        public List getList(){
            return productosList;
        }
        
        public ProductosTableModel(){
            super();
            productosList = new LinkedList<Productos>();
        }
        
        @Override
        public int getRowCount() {
            return productosList.size();
        }

        @Override
        public int getColumnCount() {
            return columnNames.length;
        }
        
        @Override
        public String getColumnName(int column) {
            return columnNames[column];
        }

        @Override
        public Object getValueAt(int rowIndex, int columnIndex) {
            String mensaje = "Error: Datos No Inicializados";
            //Abrir una session conectar el objeto a la session
            Productos p = productosList.get(rowIndex);
            switch (columnIndex){
                case CAMPO_ID: return p.getId();
                case CAMPO_TIPO_PRODUCTO: return null != p ? p.getTipoProducto(): mensaje;    //return "A Mostrar Tipo Producto";
                case CAMPO_NOMBRE: return p.getNombre() ;
                case CAMPO_TIPO_PRESENTACION: return null != p.getTipoPresentacion() ? p.getTipoPresentacion() : mensaje; //return "A Mostrar Tipo Presentacion";
                case CAMPO_FABRICANTE: return p.getFabricante() ;
                case CAMPO_REGISTRANTE: return p.getRegistrante();
                case CAMPO_TOXICIDAD: return p.getToxicidad() ;
                default: return "No hay datos para mostrar";    
            }
        }
    
    }
    
    //Clase para las peticiones en background
    
    private class PeticionTablaWorker extends SwingWorker<ProductosTableModel, Productos> {

        @Override
        protected ProductosTableModel doInBackground() throws Exception {
            
            //Aca se ara la solicitud para pedir los datos a la base de datos
            //
            StatusDisplayer.getDefault().setStatusText("Buscando datos desde la BBDD",1000);
            InterfaceProductos ia = Lookup.getDefault().lookup(InterfaceProductos.class);
            //Verificar que no sea null producto
            //Le hago dormir para que busque con mas datos cargados en el campo
            Thread.sleep(400);
            if (!this.isCancelled()){
                List<Productos> list = ia.getFindProductos(CampoNombreProducto.getText());
                tablaModel.getList().clear();
                tablaModel.getList().addAll(list);
            }    
            return tablaModel;
        }

        @Override
        protected void done() {
//            super.done();
            //Una vez que termina obtener los datos, cargar los datos en la lista
            //llamar al metodo que hace que se pinte la GUI
//            try{
               //Esta funcion es llamada desde el EDT, entonces desde aui puedo actualizar la vista
               //Probar si actualiza la vista de la tabla crear
               int cantidad = tablaModel.getList().size();
               CampoResultados.setText(MENSAJE_RESULTADO + cantidad ); 
               tablaModel.fireTableDataChanged();
               StatusDisplayer.getDefault().setStatusText("Consulta finalizada", 1000);
               CampoResultados.setVisible(true);
               //TablaProductos.setModel(get()); 
//            }
//            catch(ExecutionException ee) {
//                ee.printStackTrace();
            
//            }
//            catch(InterruptedException ie) {
//               ie.printStackTrace();
//            }
        }

    }
}
